#include "RoAbstractComponent.h"
#include "RoAbstractModule.h"


RoAbstractModule::RoAbstractModule(QObject * parent):
    super(parent),
    logTraffic(false)
{
    setName( "MODULE_" + QString::number(qrand()) );
}


RoAbstractModule::~RoAbstractModule()
{
}


RoAbstractComponent * RoAbstractModule::findComponent(QString name)
{
    return findChild<RoAbstractComponent*>(name);
}


QList<RoAbstractComponent*> RoAbstractModule::findComponents()
{
    return findChildren<RoAbstractComponent*>();
}


void RoAbstractModule::presenceEvent(RoXmlStream *, RoInfoStanza)
{
    // Default implementation.
    // Does nothing.
}


void RoAbstractModule::recieve_own_stanza(RoStanza stanza)
{
    QString addressee = stanza.to();
    QString stanzaTag = stanza.documentElement().tagName();

    // Предварительная проверка соответствия протоколу
    if ( stanzaTag == "error" )
    {
        // ok
    }
    else if ( stanzaTag == "info" )
    {
        RoInfoStanza info(stanza);
        if ( info.name() == "presence" )
            presenceEvent(qobject_cast<RoXmlStream*>(sender()), info);
    }
    else if ( stanzaTag == "iq" )
    {
        QString type = stanza.type();
        if ( type != "request" and
             type != "datum" and
             type != "result" and
             type != "error" )
        {
            sendStanza( RoErrorStanza(RoErrorStanza::UnsupportedStanzaType)
                        .setAttribute("to", stanza.from())
                        .setAttribute("from", name())
                        .setBodyAttribute("rid", stanza.id().toString()) );
            return;
        }
    }
    else // wrong stanza
    {
        sendStanza( RoErrorStanza(RoErrorStanza::UnsupportedStanzaType)
                    .setAttribute("to", stanza.from())
                    .setAttribute("from", name())
                    .setBodyAttribute("rid", stanza.id().toString()) );
        return;
    }

    // корректные строфы доставляем компонентам
    if ( addressee.isEmpty() )
    {
        if ( stanza.documentElement().tagName() == "info" )
        {
            RoInfoStanza info(stanza);
        }

        foreach ( RoAbstractComponent * component, findComponents() )
            component->recieve_own_stanza(stanza);
    }
    else
    {
        RoAbstractComponent * component = findComponent(addressee);
        if ( component )
            component->recieve_own_stanza(stanza);
        else
            sendStanza(RoIqStanza::createError( RoIqStanza::RecipientUnknown,
                                                stanza.from(), // to
                                                stanza.id(), // rid
                                                name() )); // from
    }
}
